// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cc/test/task_graph_runner_test_template.h"

namespace cc {

const int TaskGraphRunnerTestBase::kNamespaceCount;

void TaskGraphRunnerTestBase::SetTaskGraphRunner(
    TaskGraphRunner* task_graph_runner)
{
    task_graph_runner_ = task_graph_runner;
}

void TaskGraphRunnerTestBase::ResetIds(int namespace_index)
{
    run_task_ids_[namespace_index].clear();
    on_task_completed_ids_[namespace_index].clear();
}

void TaskGraphRunnerTestBase::RunAllTasks(int namespace_index)
{
    task_graph_runner_->WaitForTasksToFinishRunning(
        namespace_token_[namespace_index]);

    Task::Vector completed_tasks;
    task_graph_runner_->CollectCompletedTasks(namespace_token_[namespace_index],
        &completed_tasks);
    for (Task::Vector::const_iterator it = completed_tasks.begin();
         it != completed_tasks.end(); ++it) {
        FakeTaskImpl* task = static_cast<FakeTaskImpl*>(it->get());
        task->OnTaskCompleted();
    }
}

void TaskGraphRunnerTestBase::RunTaskOnWorkerThread(int namespace_index,
    unsigned id)
{
    base::AutoLock lock(run_task_ids_lock_);
    run_task_ids_[namespace_index].push_back(id);
}

void TaskGraphRunnerTestBase::OnTaskCompleted(int namespace_index,
    unsigned id)
{
    on_task_completed_ids_[namespace_index].push_back(id);
}

const std::vector<unsigned>& TaskGraphRunnerTestBase::run_task_ids(
    int namespace_index)
{
    return run_task_ids_[namespace_index];
}

const std::vector<unsigned>& TaskGraphRunnerTestBase::on_task_completed_ids(
    int namespace_index)
{
    return on_task_completed_ids_[namespace_index];
}

void TaskGraphRunnerTestBase::ScheduleTasks(
    int namespace_index,
    const std::vector<TaskInfo>& tasks)
{
    Task::Vector new_tasks;
    Task::Vector new_dependents;
    TaskGraph new_graph;

    for (std::vector<TaskInfo>::const_iterator it = tasks.begin();
         it != tasks.end(); ++it) {
        scoped_refptr<FakeTaskImpl> new_task(
            new FakeTaskImpl(this, it->namespace_index, it->id));
        new_graph.nodes.push_back(
            TaskGraph::Node(new_task.get(), it->category, it->priority, 0u));
        for (unsigned i = 0; i < it->dependent_count; ++i) {
            scoped_refptr<FakeDependentTaskImpl> new_dependent_task(
                new FakeDependentTaskImpl(this, it->namespace_index,
                    it->dependent_id));
            new_graph.nodes.push_back(TaskGraph::Node(
                new_dependent_task.get(), it->category, it->priority, 1u));
            new_graph.edges.push_back(
                TaskGraph::Edge(new_task.get(), new_dependent_task.get()));

            new_dependents.push_back(new_dependent_task.get());
        }

        new_tasks.push_back(new_task.get());
    }

    task_graph_runner_->ScheduleTasks(namespace_token_[namespace_index],
        &new_graph);

    dependents_[namespace_index].swap(new_dependents);
    tasks_[namespace_index].swap(new_tasks);
}

void TaskGraphRunnerTestBase::FakeTaskImpl::RunOnWorkerThread()
{
    test_->RunTaskOnWorkerThread(namespace_index_, id_);
}

void TaskGraphRunnerTestBase::FakeTaskImpl::OnTaskCompleted()
{
    test_->OnTaskCompleted(namespace_index_, id_);
}

} // namespace cc
